package com.anytron.aop;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.anytron.annotation.TimedCount;

import io.micrometer.core.instrument.Metrics;

@Aspect
@Component
public class TimedCountAspect {

	// 切入所有TimedCount注解,根据自己的TimedCount位置修改
	@Around("execution (@com.anytron.annotation.TimedCount * *.*(..))")
	public Object MetricsCollector(ProceedingJoinPoint joinPoint) throws Throwable {
		long timeMillis = System.currentTimeMillis();
		Signature signature = joinPoint.getSignature();
		MethodSignature msg = (MethodSignature) signature;
		Object target = joinPoint.getTarget();
		// 获取注解标注的方法
		Method method = target.getClass().getMethod(msg.getName(), msg.getParameterTypes());
		// 通过方法获取注解
		TimedCount annotation = method.getAnnotation(TimedCount.class);
		boolean closeCount = annotation.closeCount();
		boolean closeTimed = annotation.closeTimed();
		boolean isJustErrorCount = annotation.isJustErrorCount();
		String name = "http.request";
		String value = annotation.value();
		if (StringUtils.isNotBlank(value)) {
			name = value.trim();
		}
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		// 获取接口 uri
		String api = request.getServletPath();
		// 获取请求方式 GET/POST/...
		String type = request.getMethod();
		String[] tags = new String[4];
		tags[0] = "api";
		tags[1] = api;
		tags[2] = "type";
		tags[3] = type;
		// 判断tags
		String[] extraTags = annotation.extraTags();
		if (extraTags != null && extraTags.length > 0) {
			if (extraTags.length % 2 == 1) {
				throw new IllegalArgumentException("size must be even, it is a set of key=value pairs");
			}
			for (String string : extraTags) {
				if (StringUtils.isBlank(string)) {
					throw new IllegalArgumentException("tags value or key cant be empty");
				}
			}
			tags = ArrayUtils.addAll(tags, extraTags);
		}
		// 请求次数加1
		// 自定义的指标名称：xxx.xxx.all	指标包含数据
		if (!closeCount) {
			if (!isJustErrorCount) {
				Metrics.counter(name + ".all", tags).increment();
			}
		}
		Object object;
		try {
			object = joinPoint.proceed();
		} catch (Exception e) {
			// 请求失败次数加1
			if (!closeCount) {
				Metrics.counter(name + ".error", tags).increment();
			}
			throw e;
		} finally {
			if (!closeTimed) {
				long f = System.currentTimeMillis();
				long l = f - timeMillis;
				// 记录请求响应时间
				Metrics.timer(name + ".time", tags).record(l, TimeUnit.MILLISECONDS);
			}
		}
		return object;
	}
}
